package jgo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jgo.core.ConfigPlugin;
import jgo.core.ErrorHandlerPlugin;
import jgo.core.MiddlewarePlugin;
import jgo.core.ServerPlugin;
import jgo.plugin.TemplateEnginePlugin;
import jgo.plugins.server.SimpleServerPlugin;

import ch.qos.logback.classic.Level;

public class JGo {

	public Logger logger = LoggerFactory.getLogger(JGo.class);

	public List<Plugin> plugins = new ArrayList<>();
	public Map<Class<?>, Plugin> pluginMap = new HashMap<>();
	public boolean continueOnPluginInitError;
	public RouterPlugin router;
	public ConfigPlugin configPlugin;
	public ErrorHandlerPlugin errorHandler;
	public TemplateEnginePlugin templateEngine;
	private List<Plugin> middlewarePlugins = new ArrayList<>();

	public JGo() {
		logger.info("初始化 JGo 框架");
	}

	public static JGo server() {
		JGo g = JGo.one().use(new SimpleServerPlugin());

		g.run();
		return g;
	}

	public static JGo one() {
		JGo g = new JGo();
		
		g.use(new RouterPlugin().addRoute(Http.GET, "/", (ctx) -> {

			ctx.string("OK");

		}));
		g.run();
		return g;
	}

	public JGo use(Plugin plugin) {
		logger.debug("添加插件: {}", plugin.getClass().getSimpleName());
		try {
			plugin.init(this);
			plugins.add(plugin);
			pluginMap.put(plugin.getClass(), plugin);
			if (plugin instanceof MiddlewarePlugin) {
				middlewarePlugins.add(plugin);
				logger.info("{}   添加为中间件", plugin.getClass().getSimpleName());
			} else if (plugin instanceof RouterPlugin) {
				router = (RouterPlugin) plugin;
				logger.info("RouterPlugin       初始化完成");
			} else if (plugin instanceof ConfigPlugin) {
				configPlugin = (ConfigPlugin) plugin;
				logger.info("ConfigPlugin {} 初始化完成", plugin.getClass().getSimpleName());
			} else if (plugin instanceof ErrorHandlerPlugin) {
				errorHandler = (ErrorHandlerPlugin) plugin;
				logger.info("ErrorHandlerPlugin 初始化完成");
			} else if (plugin instanceof TemplateEnginePlugin) {
				templateEngine = (TemplateEnginePlugin) plugin;
				logger.info("TemplatePlugin     初始化完成");
			}
		} catch (Exception e) {
			handlePluginInitError(plugin, e);
		}
		return this;
	}

	private void handlePluginInitError(Plugin plugin, Exception e) {
		logger.error("初始化插件 {} 失败", plugin.getClass().getSimpleName(), e);
		if (!continueOnPluginInitError) {
			throw new RuntimeException("插件初始化失败，停止启动", e);
		}
		logger.warn("继续启动，但插件 {} 未添加", plugin.getClass().getSimpleName());
	}

	public void handleRequest(Context ctx) {
		logger.debug("处理请求: {} {}", ctx.getMethod(), ctx.getPath());
		try {
			// 执行中间件链
			executeMiddlewareChain(ctx);

			// 如果中间件没有处理请求，执行路由逻辑
			if (!ctx.isHandled()) {
				handleRouting(ctx);
			}
		} catch (Exception e) {
			logger.error("请求处理出错", e);
			handleError(ctx, e);
		}
	}

	private void executeMiddlewareChain(Context ctx) {
		final int[] index = { 0 };
		Handler next = new Handler() {
			@Override
			public void handle(Context context) {
				while (index[0] < middlewarePlugins.size()) {
					Plugin plugin = middlewarePlugins.get(index[0]++);
					if (plugin instanceof MiddlewarePlugin) {
						((MiddlewarePlugin) plugin).handle(context, this);
						return; // 让中间件控制是否继续执行
					}
				}
				// 所有中间件执行完毕
			}
		};
		next.handle(ctx);
	}

	private void handleRouting(Context ctx) {
		if (router == null) {
			logger.error("未配置 RouterPlugin");
			ctx.status(Http.NOT_FOUND).string("未找到");
			return;
		}

		Route route = router.findRoute(ctx.getMethod(), ctx.getPath());
		if (route == null) {
			logger.warn("未找到路由: {} {}", ctx.getMethod(), ctx.getPath());
			ctx.status(Http.NOT_FOUND).string("未找到");
			return;
		}

		logger.debug("找到路由，执行处理器");
		route.handler.handle(ctx);
	}

	private void handleError(Context ctx, Exception e) {
		if (errorHandler != null) {
			errorHandler.handle(ctx, e);
		} else {
			logger.error("Unhandled error in request processing", e);
			ctx.status(Http.INTERNAL_SERVER_ERROR).string("Internal Server Error");
		}
	}

	public JGo run() {
		logger.info("启动 JGo 应用");


		// 然后启动所有 ServerPlugin
		for (Plugin plugin : plugins) {
			if (plugin instanceof ServerPlugin) {
				logger.info("启动 ServerPlugin: {}", plugin.getClass().getSimpleName());
				((ServerPlugin) plugin).start(this);
			}
		}

		logger.info("JGo 应用运行中。按 Ctrl+C 停止。");

		return this;
	}

	@SuppressWarnings("unchecked")
	public <T extends Plugin> T getPlugin(Class<T> pluginClass) {
		logger.debug("Getting plugin of type: {}", pluginClass.getSimpleName());
		return (T) pluginMap.get(pluginClass);
	}

	public String getConfig(String key) {
		if (configPlugin == null) {
			throw new IllegalStateException("ConfigPlugin 未初始化");
		}
		return configPlugin.getConfig(key);
	}

	public String getConfig(String pluginName, String key) {
		if (configPlugin == null) {
			throw new IllegalStateException("ConfigPlugin 未初始化");
		}
		return configPlugin.getConfig(pluginName, key);
	}

	// 添加便捷的路由方法
	public JGo get(String path, Handler handler) {
		if (router == null) {
			throw new IllegalStateException("RouterPlugin 未初始化");
		}
		router.addRoute(Http.GET, path, handler);
		return this;
	}

	public JGo post(String path, Handler handler) {
		if (router == null) {
			throw new IllegalStateException("RouterPlugin 未初始化");
		}
		router.addRoute(Http.POST, path, handler);
		return this;
	}

	// 添加其他HTTP方法...

	// 移除旧的 staticFiles 方法
	// public JGo staticFiles(String directory) {
	// // 实现静态文件服务逻辑
	// logger.info("Serving static files from directory: {}", directory);
	// return this;
	// }

	public String renderTemplate(String template, Object data) {
		if (templateEngine == null) {
			logger.error("TemplatePlugin 未初始化");
			throw new RuntimeException("TemplatePlugin 未初始化");
		}
		logger.debug("渲染模板: {}", template);
		return templateEngine.render(template, data);
	}

	public void shutdown() {
		logger.info("正在关闭 JGo 应用");
		// 不再调用插件的 destroy 方法
		logger.info("JGo 应用已关闭");
	}

	public void setLogLevel(String level) {
		ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
		root.setLevel(Level.toLevel(level));
	}

	public RouteGroup group(String prefix) {
		return new RouteGroup(prefix, this);
	}

	public class RouteGroup {
		private String prefix;
		private JGo jgo;

		public RouteGroup(String prefix, JGo jgo) {
			this.prefix = prefix;
			this.jgo = jgo;
		}

		public RouteGroup get(String path, Handler handler) {
			jgo.get(prefix + path, handler);
			return this;
		}

		public RouteGroup post(String path, Handler handler) {
			jgo.post(prefix + path, handler);
			return this;
		}

		// 添加其他HTTP方法...
	}

	public JGo get(String path, Handler... handlers) {
		if (router == null) {
			throw new IllegalStateException("RouterPlugin 未初始化");
		}
		router.addRoute(Http.GET, path, combineHandlers(handlers));
		return this;
	}

	private Handler combineHandlers(Handler... handlers) {
		return ctx -> {
			for (Handler handler : handlers) {
				handler.handle(ctx);
				if (ctx.isHandled()) {
					break;
				}
			}
		};
	}

	public JGo staticFiles(String urlPath, String directory) {
//		use(new StaticFilePlugin(urlPath, directory));
		
		logger.warn("未实现 使用StaticFilePlugin实现");
		return this;
	}

	public void printRoutes() {
		if (router == null) {
			logger.warn("RouterPlugin 未初始化，没有可用的路由信息");
			return;
		}
		logger.info("注册的路由：");
		for (Route route : router.routes) {
			logger.info("{} {}", route.method, route.path);
		}
	}
}